/**
 * @addtogroup ring_queue.h
 * ring_queue.h
 * @{
 */
/**
 * @file ofc_ring_queue.h
 * @brief 循环队列,一读一写线程安全,无需加锁 
 * @note 队列缓冲区使用后注意内存的释放.
 
 * ![队列中储存](@ref ofc_ring_queue.png)
 
 * @author Leo
 * @date 2020-4-2
 * @version 1.0

 * @par          修改日志
 * <table>
 * <tr><th>Date        <th>Version               <th>Author          <th>Description
 * <tr><td>2020-4-2   <td>1.0                   <td>Leo             <td>创建初始版本
 * @copyright 杭州鸿泉物联网技术股份有限公司
 */

#ifndef _OFC_RING_QUEUE_H_
#define _OFC_RING_QUEUE_H_

#include "ofc_object.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * 构造一个循环缓冲区对象
 * @par 示例
 * @code
 * 创建队列对象:
   void *items[64];
   TOfRingQueue queue;
   TOfRingQueueCreate(&queue, items, sizeof(items) / sizeof(items[0]));
   // ...
   DestroyObject((TOfObject *)&queue);

 * 两个线程,一读一写
	 thread1:
	   void *item;
	   ...
	   TOfRingQueuePush(&queue, item);
	
	 thread2:
	    void *item = TOfRingQueuePop(&queue);
	    ...
 * @endcode
*/
typedef struct TOfRingQueueTag TOfRingQueue;
struct TOfRingQueueTag
{
PROTECTED
    TOfObject parent_;   ///<基类
    TOfVirtualMethod Destroy_;  ///<析构函数

PRIVATE
    void **items_;  ///< 存放队列项的缓冲区
    void **end_pos_;  ///< 队列项的尾指针
    void **read_pos_;  ///< 队列项当前读取指针
    void **write_pos_;  ///< 队列项当前写入指针
    UInt32 write_count_;  ///< 队列项写入数
    UInt32 read_count_;  ///< 队列项读取数
};

/**
 * 类的构造函数
 * @param self: 对象实例指针
 * @param items: 用于存放队列项的缓冲区
 * @param item_count: items中可以存放的队列项数
 * @return 返回创建是否成功; 创建成功返回True,参数错误返回False
 * @note 若采用此方法创建对象,需采用[OfDestroyObject](@ref OfDestroyObject)函数销毁对象
 */
Bool TOfRingQueueCreate(TOfRingQueue *self, void *items, Int32 item_count);

/**
 * 创建一个环形队列
 * @param items: 用于存放队列项的缓冲区
 * @param item_count: items中可以存放的队列项数
 * @return 返回创建的对象,创建失败返回NULL
 * @note 
 *    - 创建一个缓冲区之前,若没有执行[OfSetMallocProc](@ref OfSetMallocProc),则缓冲区会创建失败,无法分配空间.详细请参见[OfSetMallocProc](@ref OfSetMallocProc)
 *    - 若采用此方法创建对象,需采用[OfFreeObject](@ref OfFreeObject)函数释放内存.详细请参见[OfFreeObject](@ref OfFreeObject)
 */
TOfRingQueue *OfCreateRingQueue(void *items, Int32 item_count);


/**
 * 压一个队列项到队列
 * @note 仅用于单线程(中断)操作
 * @param self: 对象实例
 * @param item: 压入的队列项
 * @return 压入成功返回True,否则返回False(失败的原因是当前队列无空闲项)
 */
Bool TOfRingQueuePush(TOfRingQueue *self, const void *item);

/**
 * 取出队列中最前面的项,该项将从队列中移除
 * @note 仅用于单线程(中断)操作
 * @param self: 对象实例
 * @return 返回取出的项
 */
void *TOfRingQueuePop(TOfRingQueue *self);

/**
 * 读出队列中最前面的项,该项不从队列中移除
 * @note 仅用于单线程(中断)操作
 * @param self: 对象实例
 * @return 返回队列项; 如果队列为空,返回NULL
 */
void *TOfRingQueuePeek(TOfRingQueue *self);

/**
 * 清除所有写入队列项目
 * @note 仅用于单线程(中断)操作,且必须和调用TOfRingQueuePop的线程(中断)是同一个线程(中断)
 * @param self: 对象实例
 * @return 无返回值
 */
void TOfRingQueueClear(TOfRingQueue *self);

/**
 * 返回队列项的总数(包括数据项和空闲项目,=构造函数的参数item_count)
 * @param self: 对象实例
 * @return 返回队列项的总数
 */
Int32 TOfRingQueueSize(TOfRingQueue *self);

/**
 * 返回空闲项个数
 * @param self: 对象实例
 * @return 返回空闲项个数
 */
Int32 TOfRingQueueFreeCount(TOfRingQueue *self);

/**
 * 返回当前队列中队列项的个数(即有数据项的项个数)
 * @param self: 对象实例
 * @return 返回队列项个数
 */
Int32 TOfRingQueueCount(TOfRingQueue *self);

#ifdef __cplusplus
}  // extern "C"
#endif

#endif // _OFC_RING_QUEUE_H_

/**
 * @}
 */
